﻿using System;
using System.Net.Mail;
using System.Text;
using System.Web;
using BikeBouncer.BusinessLayer.Entities;
using Devv.Core.Utils;

namespace BikeBouncer.BusinessLayer
{
	public class MailManager
	{
		#region Properties

		public static String TemplatesPath
		{
			get
			{
				return ConfigUtil.GetConfig("BikeBouncer.Email.TemplatesPath");
			}
		}

		public static MailAddress DefaultEmail
		{
			get
			{
				return new MailAddress(ConfigUtil.GetConfig("BikeBouncer.Email.Default"), ConfigUtil.GetConfig("BikeBouncer.Email.DefaultName"));
			}
		}

		#endregion

		#region Registration emails

		public static void UserRegistrationComplete(User user)
		{
			MailMessage msg = GetMessage("UserRegistrationComplete", GetSubject("UserRegistrationComplete"));

			msg.Body = ReplaceKeywords(msg.Body, user);
			msg.Body = ReplaceKeywords(msg.Body, "ACTIVATION", User.EmailToActivationKey(user.Email));
			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);

			msg.To.Add(new MailAddress(user.Email));

			Send(msg);
		}

		public static void ItemRegistrationComplete(Item item)
		{
			MailMessage msg = GetMessage("ItemRegistrationComplete", GetSubject("ItemRegistrationComplete"));

			msg.Body = ReplaceKeywords(msg.Body, item);
			msg.Body = ReplaceKeywords(msg.Body, item.User);
			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);

			msg.To.Add(new MailAddress(item.User.Email));

			Send(msg);
		}

		public static void RegistrationDuplicateSerial(Item item, Item matched)
		{
			MailMessage msg = GetMessage("ItemRegistrationDuplicateSerial", GetSubject("ItemRegistrationDuplicateSerial"));

			msg.Subject += ": " + item.Serial;

			msg.Body = ReplaceKeywords(msg.Body, item);
			msg.Body = ReplaceKeywords(msg.Body, HttpContext.Current);
			msg.Body = ReplaceKeywords(msg.Body, "MATCHED_ID", matched.Id);
			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);

			msg.To.Add(new MailAddress(GetEmailAddress("Alerts"), DefaultEmail.DisplayName));

			Send(msg);
		}

		public static void RecoverPassword(UserPasswordRecovery rec)
		{
			MailMessage msg = GetMessage("RecoverPassword", GetSubject("RecoverPassword"));

			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);
			msg.Body = ReplaceKeywords(msg.Body, "EXPIRY_DATE", DateTime.Now.AddDays(2).ToString("f"));
			msg.Body = ReplaceKeywords(msg.Body, "RECOVERY_KEY", rec.RecoveryKey);

			Send(msg);
		}

		#endregion

		#region Item status

		public static void ItemGotLost(Note note)
		{
			MailMessage msg = GetMessage("ItemGotLost", GetSubject("ItemGotLost"));

			msg.Subject += ": " + note.Item.Title;

			msg.Body = ReplaceKeywords(msg.Body, note);
			msg.Body = ReplaceKeywords(msg.Body, note.Item);
			msg.Body = ReplaceKeywords(msg.Body, note.Address);
			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);
			msg.Body = ReplaceKeywords(msg.Body, "USER", note.Item.User.ToString());

			msg.To.Add(new MailAddress(note.Item.User.Email));

			Send(msg);
		}

		public static void ItemGotStolen(Note note)
		{
			MailMessage msg = GetMessage("ItemGotStolen", GetSubject("ItemGotStolen"));

			msg.Subject += ": " + note.Item.Title;

			msg.Body = ReplaceKeywords(msg.Body, note);
			msg.Body = ReplaceKeywords(msg.Body, note.Item);
			msg.Body = ReplaceKeywords(msg.Body, note.Address);
			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);
			msg.Body = ReplaceKeywords(msg.Body, "USER", note.Item.User.ToString());
			
			msg.To.Add(new MailAddress(note.Item.User.Email));

			Send(msg);
		}

		public static void NoteAdded(Note note)
		{
			MailMessage msg = GetMessage("NoteAdded", GetSubject("NoteAdded"));

			msg.Subject += ": " + note.Item.Title;

			msg.Body = ReplaceKeywords(msg.Body, note);
			msg.Body = ReplaceKeywords(msg.Body, note.Item);
			msg.Body = ReplaceKeywords(msg.Body, note.Address);
			msg.Body = ReplaceKeywords(msg.Body, "BASEDOMAIN", Settings.BaseDomain);
			msg.Body = ReplaceKeywords(msg.Body, "USER", note.Item.User.ToString());

			msg.To.Add(new MailAddress(note.Item.User.Email));

			Send(msg);
		}

		#endregion

		#region Black Market emails

		public static void SuggestBlackMarket(BlackMarket market)
		{
			MailMessage msg = GetMessage("SuggestBlackMarket", GetSubject("SuggestBlackMarket"));

			msg.Subject += ": " + market.Title;
			msg.Body = ReplaceKeywords(msg.Body, market);

			Send(msg);
		}

		#endregion

		#region Contact

		public static void Contact(String name, String email, String subject, String message)
		{
			MailMessage msg = GetMessage("Contact", subject);

			msg.Body = ReplaceKeywords(msg.Body, "MESSAGE", message);

			Send(msg);
		}

		#endregion

		#region Replace keywords

		private static String ReplaceKeywords(String body, Address adr)
		{
			body = ReplaceKeywords(body, "ADDRESS", adr.ToString(", "));
			body = ReplaceKeywords(body, "ADDRESS_PHONE", adr.Phone);

			return body;
		}

		private static String ReplaceKeywords(String body, Item item)
		{
			body = ReplaceKeywords(body, "ITEM_ID", item.Id);
			body = ReplaceKeywords(body, "ITEM_TITLE", item.Title);
			body = ReplaceKeywords(body, "ITEM_MAKER", item.Maker.Title);
			body = ReplaceKeywords(body, "ITEM_SERIAL", item.Serial);

			return body;
		}

		private static String ReplaceKeywords(String body, Note note)
		{
			body = ReplaceKeywords(body, "NOTE_DETAILS", note.Details);
			body = ReplaceKeywords(body, "NOTE_POSTEDDATE", note.PostedDate.ToShortDateString());
			body = ReplaceKeywords(body, "NOTE_REFERENCEDATE", note.ReferenceDate.ToShortDateString());

			return body;
		}

		private static String ReplaceKeywords(String body, User user)
		{
			body = ReplaceKeywords(body, "USER_ID", user.Id);
			body = ReplaceKeywords(body, "USER_EMAIL", user.Email);

			if (!String.IsNullOrEmpty(user.Password))
			{
				String password = "*" + user.Password.Substring(1, user.Password.Length - 2) + "*";
				body = ReplaceKeywords(body, "USER_PASSWORD", password);
			}

			return body;
		}

		private static String ReplaceKeywords(String body, BlackMarket market)
		{
			body = ReplaceKeywords(body, "MARKET_ID", market.Id);
			body = ReplaceKeywords(body, "MARKET_TITLE", market.Title);
			body = ReplaceKeywords(body, "MARKET_ADDRESS", market.Address.ToString("<br />"));

			return body;
		}

		private static String ReplaceKeywords(String body, HttpContext context)
		{
			body = ReplaceKeywords(body, "USER_IP", context.Request.UserHostAddress);

			return body;
		}

		private static String ReplaceKeywords(String body, String keyword, Int32 value)
		{
			return ReplaceKeywords(body, keyword, value.ToString());
		}

		private static String ReplaceKeywords(String body, String keyword, String value)
		{
			return body.Replace("[[" + keyword + "]]", value);
		}

		#endregion

		#region Internal implementation

		private static String GetEmailAddress(String email)
		{
			return HttpContext.GetGlobalResourceObject("MailManager", "EmailAddress_" + email).ToString();
		}

		private static String GetSubject(String subject)
		{
			return HttpContext.GetGlobalResourceObject("MailManager", "Subject_" + subject).ToString();
		}

		private static MailMessage GetMessage(String template, String subject)
		{
			MailMessage msg = new MailMessage();

			msg.BodyEncoding = Encoding.UTF8;
			msg.IsBodyHtml = true;

			msg.Subject = subject;
			msg.Body = IOUtil.ReadFile(TemplatesPath + "BaseTemplate.htm");
			msg.Body = ReplaceKeywords(msg.Body, "TEMPLATE", IOUtil.ReadFile(TemplatesPath + template + ".htm"));
			msg.Body = ReplaceKeywords(msg.Body, "SUBJECT", subject);

			return msg;
		}

		private static void Send(MailMessage msg)
		{
			if (msg.From == null || String.IsNullOrEmpty(msg.From.Address))
			{
				msg.From = DefaultEmail;
			}

			if (msg.To.Count < 1)
			{
				msg.To.Add(DefaultEmail);
			}

			try
			{
				MailUtil.Send(msg, true);
			}
			catch (Exception ex)
			{
				ErrorManager.Log(ex, "Could not send email");
			}
		}

		#endregion
	}
}